module ysyx_23060189_AXI_Lite_slave #
(
  parameter addrwidth = 32,
  parameter datawidth = 32
)
(
  /* Slave <=> Slave interface */
  output reg                    ren,
  output reg  [addrwidth-1:0]   raddr,
  input  wire [datawidth-1:0]   rdata,
  input  wire                   rvalid,

  output reg                    wen,
  output reg  [addrwidth-1:0]   waddr,
  output reg  [datawidth-1:0]   wdata,
  output wire [7:0]             wmask,
  input  wire                   wdone,

  /* Slave interface <=> Arbiter */
  // Global
  input  wire                   ACLK,
  input  wire                   ARESETn,

  // Write address channel
  input  wire                   AWVALID,
  output reg                    AWREADY,
  input  wire [addrwidth-1:0]   AWADDR,
  input  wire [2:0]             AWPROT,

  // Write data channel
  input  wire                   WVALID,
  output reg                    WREADY,
  input  wire [datawidth-1:0]   WDATA,
  input  wire [datawidth/8-1:0] WSTRB,

  // Write response channel
  output reg                    BVALID,
  input  wire                   BREADY,
  output reg  [1:0]             BRESP,

  // Read address channel
  input  wire                   ARVALID,
  output reg                    ARREADY,
  input  wire [addrwidth-1:0]   ARADDR,
  input  wire [2:0]             ARPROT,

  // Read data channel
  output reg                    RVALID,
  input  wire                   RREADY,
  output reg  [datawidth-1:0]   RDATA,
  output reg  [1:0]             RRESP
);
  // local parameter
  localparam len = 8 - datawidth/8;

  assign wmask = {{len{1'b0}}, WSTRB};

  // output ren
  always @(posedge ACLK) begin
    if (ARESETn == 0) ren <= 1'b0;
    else if (ARREADY && ARVALID) ren <= 1'b1;
    else ren <= 1'b0;
  end

  // output wen
  always @(posedge ACLK) begin
    if (ARESETn == 0) wen <= 1'b0;
    else if ((AWREADY && AWVALID) && (WREADY && WVALID)) wen <= 1'b1;
    else wen <= 1'b0;
  end

  //---------------------
  //Write address channel
  //---------------------
  // get write address
  always @(posedge ACLK) begin
    if (ARESETn == 0) waddr <= 0;
    else if (~AWREADY && AWVALID && WVALID) waddr <= AWADDR;
    else waddr <= waddr;
  end

  // AWREADY
  always @(posedge ACLK) begin
    if (ARESETn == 0) AWREADY <= 1'b0;
    else if (~AWREADY && AWVALID && WVALID) AWREADY <= 1'b1;
    else if (BVALID && BREADY) AWREADY <= 1'b0;
    else AWREADY <= AWREADY;
  end

  //---------------------
  //Write data channel
  //---------------------
  // get write data
  always @(posedge ACLK) begin
    if (ARESETn == 0) wdata <= 0;
    else if (~WREADY && WVALID && AWVALID) wdata <= WDATA;
    else wdata <= wdata;
  end

  // WREADY
  always @(posedge ACLK) begin
    if (ARESETn == 0) WREADY <= 1'b0;
    else if (~WREADY && WVALID && AWVALID) WREADY <= 1'b1;
    else WREADY <= 1'b0;
  end

  //---------------------
  //Write response channel
  //---------------------
  // BVALID and BRESP
  always @(posedge ACLK) begin
    if (ARESETn == 0) begin
      BVALID <= 1'b0;
      BRESP  <= 2'b0;
    end
    else if (~BVALID && wdone) begin
      BVALID <= 1'b1;
      BRESP  <= 2'b0;
    end
    else if (BREADY && BVALID) begin
      BVALID <= 1'b0;
      BRESP  <= BRESP;
    end
    else begin
      BVALID <= BVALID;
      BRESP  <= BRESP;
    end
  end

  //---------------------
  //Read address channel
  //---------------------
  // ARREADY and get read addr
  always @(posedge ACLK) begin
    if (ARESETn == 0) begin
      ARREADY <= 1'b0;
      raddr   <= 0;
    end
    else if (~ARREADY && ARVALID) begin
      ARREADY <= 1'b1;
      raddr   <= ARADDR;
    end
    else begin
      ARREADY <= 1'b0;
      raddr   <= raddr;
    end
  end

  //---------------------
  //Read data channel
  //---------------------
  always @(posedge ACLK) begin
    if (ARESETn == 0) begin
      RVALID <= 1'b0;
      RRESP  <= 2'b0;
      RDATA  <= 0;
    end
    else if (~RVALID && rvalid) begin
      RVALID <= 1'b1;
      RRESP  <= 2'b0;
      RDATA  <= rdata;
    end
    else if (RVALID && RREADY) begin
      RVALID <= 1'b0;
      RRESP  <= RRESP;
      RDATA  <= RDATA;
    end
    else begin
      RVALID <= RVALID;
      RRESP  <= RRESP;
      RDATA  <= RDATA;
    end
  end
  
endmodule
